package main

import "fmt"

/*===闭包===
    - 特点：
		1. 解决局部变量不能被外部访问的一种解决方案
		2. 是把函数当作一种方法返回值的应用
	- 总结：
		1. 闭包返回匿名函数是线程共享的，函数内存地址唯一
		2. 闭包中全局变量(相对与返回函数）是线程私有的，前后多次执行想同的闭包返回函数，函数中变量地址值不同
		3. 重新调用闭包方法，前一次调用返回的函数仍然在内存中存在
*/
//TODO 闭包函数调用内存分配
func main() {
	f := closure()
	fmt.Println(f()) //2
	fmt.Println(f()) //3
	fmt.Println(f()) //4

	f2 := closure()
	/* [note] f 与 f2 函数对应的是同一个内存地址，但是f2 中局部变量内存地址进行了重新分配*/
	fmt.Println(f2()) //2
	fmt.Println(f2()) //3

	/* [note] 闭包有新的返回函数f2，但是原返回函数f仍然存在 */
	fmt.Println(f()) //5

	/* [note] 闭包返回的函数在内存中是同一个函数 */
	fmt.Printf("内存地址：[f]%p [f2]%p \n", f, f2)

	fmt.Printf("新局部变量内存地址：[f]%p [f1]%p \n", f, f2)

}

func closure() func() int {
	i := 1
	return func() int {
		fmt.Printf("当前函数变量i的地址 ：%p \n", &i)
		i = i + 1
		return i
	}
}
